package com.example.geoaimavlink_android.activity.fragment

import android.os.Bundle
import android.os.SystemClock
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.geoaimavlink_android.R
import com.example.geoaimavlink_android.utils.DateTimeUtil
import com.geoai.mavlink.geoainet.flycontroller.enums.AircraftFlyMode
import com.geoai.mavlink.util.process.ProcessController
import com.geoai.mavlink.util.process.data.ProcessTag
import com.geoai.mavlink.util.process.interfaces.RunCondition
import com.geoai.mavlink.util.process.listener.ProcessControllerListener
import com.geoai.mavlink.util.process.step.Process
import com.geoai.mavlink.util.process.step.ProcessCondition
import com.geoai.mavlink.util.process.step.ProcessRun
import com.geoai.module.common.log.EALog
import com.geoai.module.common.thread.ExecutorsManager
import com.geoai.module.common.thread.TaskType
import com.geoai.video.VideoFeederView4
import com.geoai.video.YFVParams
import kotlinx.android.synthetic.main.frag_landing_test.btn_auto_land
import kotlinx.android.synthetic.main.frag_landing_test.btn_auto_landing_test
import kotlinx.android.synthetic.main.frag_landing_test.btn_auto_rotate
import kotlinx.android.synthetic.main.frag_landing_test.btn_auto_takeoff
import kotlinx.android.synthetic.main.frag_landing_test.btn_stop_auto_landing_test
import kotlinx.android.synthetic.main.frag_landing_test.btn_take_photo
import kotlinx.android.synthetic.main.frag_landing_test.tv_drone_altitude
import kotlinx.android.synthetic.main.frag_landing_test.tv_drone_battery
import kotlinx.android.synthetic.main.frag_landing_test.tv_drone_h_speed
import kotlinx.android.synthetic.main.frag_landing_test.tv_drone_mode
import kotlinx.android.synthetic.main.frag_landing_test.tv_drone_v_speed
import kotlinx.android.synthetic.main.frag_landing_test.tv_logcat
import kotlinx.android.synthetic.main.frag_landing_test.video_feeder
import java.util.Random
import java.util.concurrent.Future
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.pow
import kotlin.math.sqrt

class AutoLandingTestFragment: BaseFragment() {

    private var mProcessControllerListener: ProcessController? = null

    private val mProcessRunning: AtomicBoolean = AtomicBoolean(false)

    private var mThread: Future<*>? = null

    private var times = 0;

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.frag_landing_test, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        tv_logcat.movementMethod = ScrollingMovementMethod.getInstance()
        initView()
        initMSDK()
        initProgress()
    }

    private fun initProgress() {
        mProcessControllerListener = ProcessController()
            .add(startTakeoff())
            .add(startTakeoffCheck())
            .add(startSleep(2))
            .add(startRotateAircraft())
            .add(startSleep(5))
            .add(startRotateAircraftCheck())
            .add(startSleep(2))
            .add(startAutoLanding())
            .add(startSleep(2))
            .add(startAutoLandingChecked())
            .add(startSleep(2))
            .add(startShoot())
            .add(startSleep(5))
            .setProcessControllerListener(object : ProcessControllerListener() {
                override fun onStep(tag: ProcessTag?) {
                    super.onStep(tag)
                    writeLogcat(DateTimeUtil.getInstance().nowTime + " - " + tag?.tag)
                    EALog.log(EALog.LogTag.RUNTIME, DateTimeUtil.getInstance().nowTime + " - " + tag?.tag)
                }

                override fun onComplete() {
                    super.onComplete()
                    times++
                    writeLogcat("------第$times 次, 测试结束------")
                    EALog.log(EALog.LogTag.RUNTIME, "------第$times 次, 测试结束------")
                    mProcessRunning.set(false)
                }
            })
    }

    private fun initMSDK() {
        msdkInfoVm.msdkInfo.observe(viewLifecycleOwner) {
            if (it.isAircraftConnected) {
                getProduct()?.flyControllerManager?.setFlyControllerStateListener {
                    activity?.runOnUiThread {
                        tv_drone_mode.text = "模式：${it.flyMode.name}"
                        tv_drone_battery.text = "电量：${getProduct()?.batteryManager?.batteryInfo?.get(0)?.batteryRemainingPercentage}"
                        tv_drone_altitude.text = "高度：${it.aircraftAltitude}"
                        tv_drone_h_speed.text = "水平速度：${sqrt(it.aircraftVelocityX.toDouble().pow(2.0) + it.aircraftVelocityY.toDouble().pow(2.0))}"
                        tv_drone_v_speed.text = "垂直速度：${it.aircraftVelocityZ}"
                    }
                }
                activity?.runOnUiThread {
                    initVideo()
                }
            } else {
                getProduct()?.flyControllerManager?.setFlyControllerStateListener(null)
            }
        }
    }

    private fun initVideo() {
        writeLogcat("api: 开始渲染主相机图传")

        video_feeder.initPlayer(
            YFVParams.Builder()
                .setPlayNode(VideoFeederView4.PlayNode.MAIN_CAM)
                .setVideoDecodeMode(VideoFeederView4.DecodeMode.H265)
                .setVideoCodecMode(VideoFeederView4.CodecMode.HARDWARE)
                .setSurfaceMode(VideoFeederView4.SurfaceMode.TEXTURE)
                .build(), VideoFeederView4::startPlayer)
    }

    private fun initView() {
        btn_auto_takeoff.setOnClickListener {
            getProduct()?.flyControllerManager?.startAircraftTakeoff(20.0f) {
                writeLogcat("api: 触发起飞至20m高")
                showToast(it?.description?:"success")
            }
        }

        btn_auto_land.setOnClickListener {
            getProduct()?.flyControllerManager?.startAircraftLand(true) {
                writeLogcat("api: 触发视觉降落")
                showToast(it?.description?:"success")
            }
        }

        btn_take_photo.setOnClickListener {
            getProduct()?.payloadManager?.camera?.startSingleCapture {
                writeLogcat("api: 触发相机拍照")
                showToast(it?.description?:"success")
            }
        }

        btn_auto_rotate.setOnClickListener {

            ExecutorsManager.get().execute("") {

                val looperTimes = Random().nextInt(20) + 20// 20-40随机数

                writeLogcat("api: 触发打开虚拟摇杆")
                getProduct()?.flyControllerManager?.setNewJoyStickEnable(true, null)

                for (i in 0 until looperTimes) {
                    getProduct()?.flyControllerManager?.sendNewJoyStickControl(0.0f, 0.0f, 0.0f, 2.0f, null)
                    SystemClock.sleep(100)
                }

                writeLogcat("api: 触发关闭虚拟摇杆")
                getProduct()?.flyControllerManager?.setNewJoyStickEnable(false, null)
            }
        }

        btn_auto_landing_test.setOnClickListener {
            EALog.log(EALog.LogTag.RUNTIME, "----开始自动化降落测试 $times")
            if (mThread != null) {
                mThread?.cancel(true)
                mThread = null
            }
            mThread = ExecutorsManager.get().submit("", TaskType.WORKER) {
                while (true) {
                    SystemClock.sleep(2000)
                    if (mProcessRunning.compareAndSet(false, true)) {//没有在执行
                        mProcessControllerListener?.start()
                    }
                }
            }
        }

        btn_stop_auto_landing_test.setOnClickListener {
            EALog.log(EALog.LogTag.RUNTIME, "----停止自动化降落测试 $times")
            mProcessRunning.set(false)
            if (mThread != null) {
                mThread?.cancel(true)
                mThread = null
            }
            mProcessControllerListener?.stop()
            getProduct()?.flyControllerManager?.stopAllAction {  }
        }
    }

    private fun writeLogcat(log: String) {
        tv_logcat?.let {
            mainHandler.post {
                tv_logcat.append(log + "\r\n")
                val offset: Int = tv_logcat.lineCount * tv_logcat.lineHeight
                if (offset > tv_logcat.height) {
                    tv_logcat.scrollTo(0, offset - tv_logcat.height)
                }
            }
        }
    }

    // -----------------流程------------------

    private fun startTakeoff() : Process {
        return ProcessRun(ProcessTag("auto: 触发自动起飞")) {
            activity?.runOnUiThread { btn_auto_takeoff.performClick() }
            it.next()
        }
    }

    private fun startTakeoffCheck() : Process {
        return ProcessCondition(ProcessTag("auto: 起飞完成检测"), object : RunCondition {
            override fun condition(): Boolean {
                return getProduct()?.flyControllerManager?.flyControllerInfo?.aircraftAltitude!! > 19.5f
            }
        }, 1, 60)
    }

    private fun startRotateAircraft(): Process {
        return ProcessRun(ProcessTag("auto: 触发随机调整航向")) {
            activity?.runOnUiThread { btn_auto_rotate.performClick() }
            it.next()
        }
    }

    private fun startRotateAircraftCheck(): Process {
        return ProcessCondition(ProcessTag("auto: 航向调整检测"), object : RunCondition{
            override fun condition(): Boolean {
                return getProduct()?.flyControllerManager?.flyControllerInfo?.flyMode == AircraftFlyMode.HOVER
            }
        }, 1, 60)
    }

    private fun startAutoLanding(): Process {
        return ProcessRun(ProcessTag("auto: 触发自动视觉降落")) {
            activity?.runOnUiThread { btn_auto_land.performClick() }
            it.next()
        }
    }

    private fun startAutoLandingChecked(): Process {
        return ProcessCondition(ProcessTag("auto: 视觉降落完成检测"), object : RunCondition{
            override fun condition(): Boolean {
                return getProduct()?.flyControllerManager?.flyControllerInfo?.isFlying == false
            }
        }, 1, 60)
    }

    private fun startShoot(): Process {
        return ProcessRun(ProcessTag("auto: 触发自动拍照")) {
            activity?.runOnUiThread { btn_take_photo.performClick() }
            it.next()
        }
    }

    private fun startSleep(second: Int): Process {
        return ProcessRun(ProcessTag("auto: 触发休眠")) {
            SystemClock.sleep((second * 1000).toLong())
            it.next()
        }
    }
}